package com.nomi.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.nomi.blog.entity.User;
import com.nomi.blog.entity.UserInfo;
import com.nomi.blog.mapper.UserInfoMapper;
import com.nomi.blog.mapper.UserMapper;
import com.nomi.blog.service.UserService;
import com.nomi.blog.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    // 邮件发送器
    @Autowired
    private JavaMailSender mailSender;

    // Redis
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${spring.mail.username}")
    private String fromEmail;

    // jwt密钥
    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.expiration}")
    private Long jwtExpiration;

    // 验证码的Redis key
    private static String VERIFICATION_CODE_KEY = "blog:verify_code";
    // 验证码的Redis key的过期时间为5分钟
    private static final int VERIFICATION_CODE_EXPIRATION = 5;

    /**
     * 注册
     *
     * @param user
     * @return
     */
    @Override
    @Transactional  // 提交事务
    public Result register(User user) {
        // 检查账号或昵称是否已存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", user.getAccount()).or().eq("nickname", user.getNickname());
        User existUser = userMapper.selectOne(queryWrapper);

        if (existUser != null) {
            return Result.fail("账号或昵称已存在");
        }

        // 加密密码
        user.setPassword(Md5Utils.encrypt(user.getPassword()));
        // 设置创建时间
        user.setCreateTime(new Date());
        // 计算码龄
        // 返回的是从 1900 年开始的年份偏移值，因此需要加 1900 才能得到当前的实际年份。
        // 获取当前年份
        int currentYear = new Date().getYear() + 1900;
        // 获取用户创建年份
        int createYear = user.getCreateTime().getYear() + 1900;
        user.setCodingYears(currentYear - createYear);

        // 保存用户
        int result = userMapper.insert(user);

        if (result > 0) {
            // 创建用户信息
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(user.getId());
            userInfo.setPersonalIntroduction("这个人很懒(╥﹏╥...)，个人介绍什么的，神马也没写");
            userInfo.setBlogIntroduction("这个人很懒(≧﹏ ≦)，博客介绍什么的，神马也没写");
            userInfo.setArticleCount(0);
            userInfo.setFollowingCount(0);
            userInfo.setFollowerCount(0);
            userInfo.setTotalViews(0);

            int resultUserInfo = userInfoMapper.insert(userInfo);
            if (resultUserInfo > 0) {
                return Result.success("注册成功", user);
            } else {
                return Result.fail("注册失败");
            }
        } else {
            return Result.fail("注册失败");
        }
    }

    /**
     * 登录
     * @param identifier
     * @param password
     * @return
     */
    @Override
    public Result login(String identifier, String password) {
        // 根据账号或昵称查询用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", identifier).or().eq("nickname", identifier);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            return Result.fail("该用户不存在");
        }

        //验证密码
        if (!Md5Utils.encrypt(password).equals(user.getPassword())) {
            return Result.fail("密码错误");
        }

        //生成JWT token
        String token = JwtUtils.generateToken(user.getId(), jwtSecret);
        System.out.println("Token:"+token);
//        System.out.println("Result User:"+user);

        return Result.success("登录成功", token);
    }

    /**
     * 发送邮件
     */
    private void sendEmail(String to,String subject ,String content){
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromEmail);     // 设置发送者
        message.setTo(to);              // 设置接收者
        message.setSubject(subject);    // 设置主题
        message.setText(content);       // 设置内容
        mailSender.send(message);       // 发送邮件
    }

    /**
     * 邮箱发送验证码
     * @param email
     * @return
     */
    @Override
    public Result<String> sendVerificationCode(String email) {
        //检查邮箱是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        User user = userMapper.selectOne(queryWrapper);

        if(user == null){
            return Result.fail("该邮箱不存在");
        }

        //生成验证码
        String code = RandomUtils.generateCode(6);

        //保存到Redis
        redisTemplate.opsForValue().set(VERIFICATION_CODE_KEY + email,code,VERIFICATION_CODE_EXPIRATION, TimeUnit.MINUTES);

        //发送邮件
        try{
            sendEmail(email,"nomi blog 博客网站账户密码重置验证码","您的验证码是："+ code + "\n有效期5分钟");
            return Result.success("验证码已发送，请查收邮箱");
        } catch (Exception e){
            e.printStackTrace();
            return Result.fail("验证码发送失败");
        }
    }

    @Override
    @Transactional
    public Result resetPassword(String email, String code, String newPassword) {
        //从Redis获取验证码
        String savedCode = redisTemplate.opsForValue().get(VERIFICATION_CODE_KEY + email);

        if(savedCode == null || !savedCode.equals(code)){
            return Result.fail("验证码错误或已过期");
        }

        //查找用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", email);
        User user = userMapper.selectOne(queryWrapper);

        if (user == null){
            return Result.fail("该用户不存在");
        }

        //更改密码
        user.setPassword(Md5Utils.encrypt(newPassword));
        int result = userMapper.update(user, queryWrapper);

        if (result > 0){
            //删除验证码
            redisTemplate.delete(VERIFICATION_CODE_KEY + email);
            return Result.success("密码重置成功");
        }else{
            return Result.fail("密码重置失败");
        }
    }

    @Override
    public Result getCurrentUserInfo() {
        //从当前线程获取用户Id
        Long userId = UserContext.getCurrentUserId();
        System.out.println("从当前线程获取用户Id:"+userId);
        if (userId == null){
            return Result.fail("用户未登录");
        }

        //查询用户信息
        User user = userMapper.selectById(userId);
        if(user == null){
            return Result.fail("用户不存在");
        }

        //不返回密码
        //user.setPassword(null);
//        System.out.println("user:"+user);

        return Result.success("获取用户信息成功",user);
    }

    /**
     * 通过用户Id获取用户信息
     * @param userId
     * @return
     */
    @Override
    public Result getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if(user == null){
            return Result.fail("用户不存在");
        }
        return Result.success("获取用户信息成功",user);
    }

    @Override
    @Transactional
    public Result updateUserInfo(User user) {
        // 从当前线程获取用户ID
        Long userId = UserContext.getCurrentUserId();

        if(userId == null){
            return Result.fail("用户未登录");
        }

        // 确保更新的是当前用户
        user.setId(userId);

        //不更新密码和创建时间
        user.setPassword(null);
        user.setCreateTime(null);

        //更新用户信息
        int result = userMapper.updateById(user);

        if(result > 0){
            return Result.success("更新用户信息成功");
        }else{
            return Result.fail("更新用户信息失败");
        }
    }

    /**
     * 上传头像
     * @param file
     * @return
     */
    @Override
    @Transactional
    public Result uploadAvatar(MultipartFile file) throws IOException {
        byte[] avatarBytes = file.getBytes();
        //打印头像字节数组
//        System.out.println("Avatar Bytes:"+ Arrays.toString(avatarBytes));
        User user = new User();
        //从当前线程获取用户Id
        Long userId = UserContext.getCurrentUserId();

        System.out.println("userId:"+userId);
        user.setId(userId);
        user.setAvatar(avatarBytes);
        int result = userMapper.updateById(user);
        if(result > 0){
            return Result.success("上传头像成功");
        }else {
            return Result.fail("上传头像失败");
        }
    }
}
